package com.lyn.serialport.control;

import android.util.Log;

import com.lyn.serialport.android_serialport_api.SerialPort;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author liuyn
 */

public class SerialPortControler {
    private static String TAG = "SerialPortControler";
    private static Map<String, Boolean> mapIsListening = new ConcurrentHashMap<>();
    private static Map<String, SerialPort> mapSerialPort = new ConcurrentHashMap<>();
    private SerialPort serialPort = null;
    private String serialPortFileName;

    /**
     * @param serialPortFileName 串口名称
     * @param baudrate 波特率
     * @param flags 0-阻塞读取，00004000-非阻塞读取
     */
    public SerialPortControler(String serialPortFileName, int baudrate, int flags){
        try {
            this.serialPortFileName = serialPortFileName;
            serialPort = new SerialPort(serialPortFileName, baudrate, flags);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 打开串口并开始监听
     * @return
     * @throws Exception
     */
//    public Observable<byte[]> statListen() throws Exception {
//        if (mapSerialPort.get(serialPortFileName) != null) {
//            throw new Exception(serialPortFileName + "串口已经在监听了");
//        }
//
//        final InputStream inputStream = serialPort.getInputStream();
//        if (inputStream == null) {
//            throw new Exception(serialPortFileName + "串口输入流有问题");
//        }
//        mapSerialPort.put(serialPortFileName, serialPort);
//        mapIsListening.put(serialPortFileName, true);
//        return Observable.create(new ObservableOnSubscribe<byte[]>() {
//            @Override
//            public void subscribe(ObservableEmitter<byte[]> emitter) throws Exception {
//                while (mapIsListening.get(serialPortFileName)) {
//                    try {
//                        byte[] buffer = new byte[1024];
//                        int size = inputStream.read(buffer);
//                        byte[] readBytes = new byte[size];
//                        System.arraycopy(buffer, 0, readBytes, 0, size);
//                        if (size > 0) {
//                            emitter.onNext(readBytes);
//                        }
//                        Thread.sleep(200);
//                    } catch (IOException e) {
//                        if (!emitter.isDisposed()) {
//                            emitter.onError(e);
//                        }
//                        e.printStackTrace();
//                        return;
//                    }
//                }
//            }
//        });
//    }

//    public Observable<Boolean> sendCMD(final byte[] cmd){
//        return Observable.create(new ObservableOnSubscribe<Boolean>() {
//            @Override
//            public void subscribe(ObservableEmitter<Boolean> emitter) throws Exception {
//                OutputStream out = serialPort.getOutputStream();
//                // 写入数据
//                try {
//                    logE( "sendCMD : "+ ByteUtil.bytes2hex(cmd));
//                    out.write(cmd);
//                    out.flush();
//                    emitter.onNext(true);
//                    emitter.onComplete();
//                } catch (IOException e) {
//                    if (!emitter.isDisposed()) {
//                        emitter.onError(e);
//                    }
//                    out.close();
//                }
//            }
//        });
//    }

    public byte[] readData() throws Exception {
        byte[] buffer = new byte[1024];
        int size = serialPort.getInputStream().read(buffer);
        byte[] readBytes = new byte[size];
        if(size > 0) System.arraycopy(buffer, 0, readBytes, 0, size);
        return readBytes;
    }

    public byte[] sendCMDSInThread(byte[] cmds) throws IOException {
        OutputStream out = serialPort.getOutputStream();
        // 写入数据
        try {
            out.write(cmds);
            out.flush();
            logE( "sendCMD ->:"+ ByteUtil.bytes2hex(cmds));
        } catch (IOException e) {
            out.close();
        }
        return cmds;
    }

//    public Observable<byte[]> sendCMDS(final byte[] cms){
//        return Observable.create(new ObservableOnSubscribe<byte[]>() {
//            @Override
//            public void subscribe(ObservableEmitter<byte[]> emitter) throws Exception {
//                OutputStream out = serialPort.getOutputStream();
//                // 写入数据
//                try {
//                    logE( "sendCMD ->:"+ ByteUtil.bytes2hex(cms));
//                    out.write(cms);
//                    out.flush();
//                    emitter.onNext(cms);
//                    emitter.onComplete();
//                } catch (IOException e) {
//                    if (!emitter.isDisposed()) {
//                        emitter.onError(e);
//                    }
//                    out.close();
//                }
//            }
//        });
//    }

    public SerialPort getSerialPort() {
        return serialPort;
    }

    /**
     * 关闭一个串口的读写
     *
     * @param serialPortFileName
     */
    public void stop(String serialPortFileName) {
        mapSerialPort.get(serialPortFileName).close();
        mapIsListening.remove(serialPortFileName);
        mapSerialPort.remove(serialPortFileName);
    }

    /**
     * 关闭所有串口的读写
     */
    public static void stopAll() {
        for (String serialPortFileName : mapSerialPort.keySet()) {
            mapSerialPort.get(serialPortFileName).close();
        }
        mapIsListening.clear();
        mapSerialPort.clear();
    }

    private void logE(String msg){
        Log.e(TAG,msg);
    }
}
